import { Component, OnInit, ChangeDetectionStrategy, Injectable, ChangeDetectorRef, ViewChild } from '@angular/core';
import { LvSelectSM, OptionItem, SelectComponent } from '@iux/live';
import { of } from 'rxjs';
import { delay, tap } from 'rxjs/operators';

interface UsersOption extends OptionItem {
  id: string;
  age: number;
  expand: boolean;
}

@Injectable()
export class DemoService {
  constructor() {}

  getUsers(len: number = 10, index: number = 0, data: string = '') {
    const users = this.initUser(len, index).filter(item => item.label.toLocaleLowerCase().includes(data.toLocaleLowerCase()));
    return of(users).pipe(delay(1500));
  }

  initUser(len?: number, index?: number) {
    const users = Array.from({ length: len }).map((item, key) => {
      const userKey = key + index;
      const userItem: UsersOption = {
        id: `uid${userKey}`,
        label: `user${userKey}`,
        value: `userValue${userKey}`,
        age: 10 + userKey,
        expand: false,
        isLeaf: true,
      };
      return userItem;
    });

    return users;
  }
}

@Component({
  selector: 'app-async-data',
  templateUrl: './async-data.component.html',
  providers: [DemoService],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AsyncDataComponent implements OnInit {
  selectModel: LvSelectSM = 'single';
  length = 10;
  index = 0;
  data: UsersOption[];
  initData: UsersOption[] = [];
  loading: boolean = false;
  value;
  singleDefault = { id: `uid20`, label: `user20`, value: `userValue20`, age: 30, expand: false, isLeaf: true };
  multipleDefault = [
    { id: `uid20`, label: `user20`, value: `userValue20`, age: 30, expand: false, isLeaf: true },
    { id: `uid30`, label: `user30`, value: `userValue30`, age: 40, expand: false, isLeaf: true },
  ];

  @ViewChild('select') lvSelect: SelectComponent;

  constructor(private demoService: DemoService, private cdr: ChangeDetectorRef) {}

  ngOnInit() {
    this.changeSelection(this.selectModel);
  }

  beforeOpen = () => {
    if (!this.data?.length) {
      this.loading = true;
      return this.getUsers(this.length).pipe(
        tap(res => {
          this.loading = false;
          this.initData = res;
          this.data = this.initData;
          this.cdr.markForCheck();
        })
      );
    } else {
      return true;
    }
  };

  getUsers(len?: number, index?: number, data?: string) {
    return this.demoService.getUsers(len, index, data);
  }

  modelChange(model) {
    this.selectModel = model;
    this.changeSelection(this.selectModel);
  }

  changeSelection(model) {
    if (model === 'single') {
      this.value = this.singleDefault;
    } else {
      this.value = this.multipleDefault;
    }
  }

  filterChange(value: string) {
    this.data = this.initData.filter(item => item.label.toLocaleLowerCase().includes(value.toLocaleLowerCase()));
  }

  updateOptions() {
    console.log('scroll end, append new 10 items.');
    if (this.loading) {
      return;
    }
    this.loading = true;
    const offsetIndex = 10;
    this.index += offsetIndex;
    this.demoService.getUsers(offsetIndex, this.index).subscribe(res => {
      this.initData = [...this.initData, ...res];
      this.data = this.initData;
      this.loading = false;
      this.cdr.markForCheck();
    });
  }

  updateSelection(value) {
    if (this.selectModel === 'single') {
      this.value = value;
      return;
    }

    const data = this.lvSelect.getSelectData();

    // 1、生成完整的valueMap
    const valueMap = new Map();
    this.value?.forEach(item => {
      valueMap.set(item.id, item); // item.id: id为lvCompareWith的值，且该值为option中存在的属性
    });

    const getSelected = nodes => {
      nodes.forEach(item => {
        if (item.selected && !valueMap.get(item.id)) {
          valueMap.set(item.id, item);
        } else if (!item.selected) {
          // 删除指定项
          valueMap.delete(item.id);
        }
      });
    };

    getSelected(data);
    this.value = Array.from(valueMap.values());
  }

  removeSelection(node) {
    this.value = this.value.filter(item => item.id !== node.id);
  }
}
